package com.open.capacity.finance.service.impl;

import com.open.capacity.common.util.XsteamUtil;
import com.open.capacity.finance.config.Globals;
import com.open.capacity.finance.dao.*;
import com.open.capacity.finance.dto.SourcePzErrorDto;
import com.open.capacity.finance.entity.*;
import com.open.capacity.reptile.entity.GdszczMaEleDeppro;
import com.open.capacity.user.model.SysCompany;
import com.open.capacity.user.service.SysCompanyService;
import com.open.capacity.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.open.capacity.commons.PageResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.open.capacity.commons.CodeEnum;

import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.commons.collections4.MapUtils;

import com.open.capacity.finance.service.SourcePzService;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
public class SourcePzServiceImpl implements SourcePzService {

    @Autowired
    private SysCompanyService companyService;

    @Autowired
    private SourceBaseKjkmDao sourceBaseKjkmDao;
    @Autowired
    private SourceBaseXmDao sourceBaseXmDao;
    @Autowired
    private SourceBaseCustomItemDao sourceBaseCustomItemDao;
    @Autowired
    private SourceBaseCustomValueDao sourceBaseCustomValueDao;

    @Autowired
    private SourceBaseKjkmExtDao sourceBaseKjkmExtDao;

    @Autowired
    private SourcePzDao sourcePzDao;

    @Autowired
    private SourceKmyeDao sourceKmyeDao;


    /**
     * 添加
     *
     * @param gl
     */
    @Transactional
    public synchronized int saveGL2db(String companyId, Integer kjnd, Integer importway, SourceGLXML gl) {
        log.info("start to save2db GL.xml");
        Date now = new Date();

        //删除旧数据
        if (importway == 1) {
            deleteGL(companyId, kjnd);
        }


        if (gl != null) {
            //1. 记账凭证
            List<SourcePz> pzList = gl.getPzList();

            //1. 基础数据-会计科目导入
            List<SourceBaseKjkm> baseKjkmList = gl.getBaseKjkmList();
            baseKjkmList.forEach(t -> {
                t.setCompanyId(companyId);
                t.setKjnd(kjnd);
                sourceBaseKjkmDao.save(t);
            });
            List<SourceBaseKjkmExt> baseKjkmExtList = gl.getBaseKjkmExtList();
            baseKjkmExtList.forEach(t -> {
                t.setCompanyId(companyId);
                t.setKjnd(kjnd);
                sourceBaseKjkmExtDao.save(t);
            });

            //2. 记账凭证导入
            if (CollectionUtils.isNotEmpty(pzList)) {
                pzList.forEach(t -> {
                    t.setCompanyId(companyId);
                    t.setUpdateTime(now);
                    sourcePzDao.save(t);
                });
            }

            //3. 科目余额及发生额导入
            List<SourceKmye> kmyeList = gl.getKmyeList();
            kmyeList = fillYe(kmyeList);
            kmyeList.forEach(t -> {
                t.setCompanyId(companyId);
                t.setUpdateTime(now);
                sourceKmyeDao.save(t);
            });
        }


        log.info("successful to save2db GL.xml ");

        return 1;
    }

    private List<SourceKmye> fillYe(List<SourceKmye> kmyeList) {
        HashMap<String, List<SourceKmye>> collect = kmyeList.stream().collect(Collectors.groupingBy(t -> t.getCompanyId() + "_" + t.getKjkmCode() + "_" + t.getKjnd() + "_" + t.getExt1() + "_" + t.getExt2() + "_" + t.getExt3() + "_" + t.getExt4() + "_" + t.getExt5() + "_" + t.getExt6(), HashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<SourceKmye>> entry : collect.entrySet()) {
            entry.getValue().sort(Comparator.comparingInt(SourceKmye::getKjqj));
            entry.getValue().forEach(t -> {
                t.setYe(entry.getValue().stream().filter(c -> c.getKjqj().equals(12)).map(c -> c.getQm()).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
            });
        }
        return kmyeList;
    }

    /**
     * 添加
     *
     * @param share
     */
    @Transactional
    public synchronized int saveSHARE2db(String companyId, Integer kjnd, Integer importway, SourceSHAREXML share) {
        log.info("start to save2db GSHARE.xml");

        //删除旧数据
        if (importway == 1) {
            deleteSHARE(companyId, kjnd);
        }

        if (share != null) {
            //1. 项目导入
            List<SourceBaseXm> xmList = share.getBaseXmList();
            if (CollectionUtils.isNotEmpty(xmList)) {
                xmList.forEach(t -> {
                    t.setCompanyId(companyId);
                    t.setKjnd(kjnd);
                    sourceBaseXmDao.save(t);
                });
            }
            List<SourceBaseCustomItem> customItemList = share.getBaseCustomItemList();
            customItemList.forEach(t -> {
                t.setCompanyId(companyId);
                t.setKjnd(kjnd);
                sourceBaseCustomItemDao.save(t);
            });
            List<SourceBaseCustomValue> customValueList = share.getBaseCustomValueList();
            customValueList.forEach(t -> {
                t.setCompanyId(companyId);
                t.setKjnd(kjnd);
                Optional<SourceBaseCustomItem> first = customItemList.stream().filter(e -> e.getCompanyId().equals(companyId) && e.getKjnd().equals(kjnd) && e.getCode().equals(t.getItemCode())).findFirst();
                t.setItemName(first.isPresent() ? first.get().getName() : null);
                sourceBaseCustomValueDao.save(t);
            });
        }

        log.info("successful to save2db SHARE.xml");

        return 1;
    }


    @Override
    public synchronized SourceGLXML parseGL(String companyId, Integer kjnd, String url) throws MalformedURLException {
        log.info("start to parse GL.xml");

        SourceGLXML glxml = null;
        if (StringUtil.isNotEmpty(url)) {
            glxml = (SourceGLXML) XsteamUtil.toBean(SourceGLXML.class, new URL(url));
        }

        List<SysCompany> companyList = companyService.findAll(new HashMap<>());
        if (glxml != null) {
            //填充科目名称
            SourceGLXML finalGlxml = glxml;
            if (glxml.getPzList() != null) {
                glxml.getPzList().forEach(t -> {
                    t.setCompanyId(companyId);
                    Optional<SourceBaseKjkm> kjkmOptional = finalGlxml.getBaseKjkmList().stream()
                            .filter(ext -> ext.getCode().equals(t.getKjkmCode()))
                            .findFirst();
                    if (kjkmOptional.isPresent()) {
                        t.setKjkmName(kjkmOptional.get().getName());
                    }
                    Optional<SysCompany> companyOptional = companyList.stream().filter(ext -> ext.getId().equals(t.getCompanyId())).findFirst();
                    if (companyOptional.isPresent()) {
                        t.setCompanyName(companyOptional.get().getFullName());
                    }
                });
            }
            glxml.getKmyeList().forEach(t -> {
                t.setCompanyId(companyId);
                Optional<SourceBaseKjkm> kjkmOptional = finalGlxml.getBaseKjkmList().stream()
                        .filter(ext -> ext.getCode().equals(t.getKjkmCode()))
                        .findFirst();
                if (kjkmOptional.isPresent()) {
                    t.setKjkmName(kjkmOptional.get().getName());
                }
                Optional<SysCompany> companyOptional = companyList.stream().filter(ext -> ext.getId().equals(t.getCompanyId())).findFirst();
                if (companyOptional.isPresent()) {
                    t.setCompanyName(companyOptional.get().getFullName());
                }
            });
        }

        log.info("successful to parse GL.xml ");
        return glxml;
    }

    @Override
    public synchronized SourceSHAREXML parseSHARE(String companyId, Integer kjnd, String url) throws MalformedURLException {
        log.info("start to parse SHARE.xml");

        SourceSHAREXML sharexml = null;
        if (StringUtil.isNotEmpty(url)) {
            sharexml = (SourceSHAREXML) XsteamUtil.toBean(SourceSHAREXML.class, new URL(url));
        }

        log.info("successful to parse SHARE.xml ");
        return sharexml;
    }

    /**
     * 删除
     *
     * @param companyId
     */
    @Transactional
    public int deleteGL(String companyId, Integer kjnd) {
        sourceBaseKjkmDao.deleteByCompanyIdAndKjnd(companyId, kjnd);
        sourceBaseKjkmExtDao.deleteByCompanyIdAndKjnd(companyId, kjnd);
        sourcePzDao.deleteByCompanyIdAndKjnd(companyId, kjnd);
        sourceKmyeDao.deleteByCompanyIdAndKjnd(companyId, kjnd);
        return 1;
    }

    /**
     * 删除
     *
     * @param companyId
     */
    @Transactional
    public int deleteSHARE(String companyId, Integer kjnd) {
        sourceBaseXmDao.deleteByCompanyIdAndKjnd(companyId, kjnd);
        sourceBaseCustomItemDao.deleteByCompanyIdAndKjnd(companyId, kjnd);
        sourceBaseCustomValueDao.deleteByCompanyIdAndKjnd(companyId, kjnd);
        return 1;
    }

    /**
     * 查询记录
     *
     * @param id
     * @return
     */
    public SourcePz findById(String id) {
        return sourcePzDao.findById(id);
    }

    /**
     * 分页
     *
     * @param params
     * @return
     */
    public PageResult<SourcePz> pageAll(Map<String, Object> params) {
        //设置分页信息，分别是当前页数和每页显示的总记录数【记住：必须在mapper接口中的方法执行之前设置该分页信息】
        if (MapUtils.getInteger(params, "page") != null && MapUtils.getInteger(params, "limit") != null)
            PageHelper.startPage(MapUtils.getInteger(params, "page"), MapUtils.getInteger(params, "limit"), true);

        List<SourcePz> list = sourcePzDao.findExt(params);
        PageInfo<SourcePz> pageInfo = new PageInfo(list);

        return PageResult.<SourcePz>builder().data(pageInfo.getList()).resp_code(CodeEnum.SUCCESS.getCode()).count(pageInfo.getTotal()).build();
    }

    /**
     * 列表
     *
     * @param params
     * @return
     */
    public List<SourcePz> findPz(Map<String, Object> params) {
        List<SourcePz> list = sourcePzDao.findPz(params);
        list.forEach(t -> {
            Optional<SysCompany> first = Globals.companyList.stream().filter(c -> c.getId().equals(t.getCompanyId())).findFirst();
            if (first.isPresent()) {
                t.setCompanyName(first.get().getFullName());
            }
        });
        return list;
    }

    /**
     * 列表
     *
     * @param params
     * @return
     */
    public List<SourcePz> findExt(Map<String, Object> params) {
        List<SourcePz> list = sourcePzDao.findExt(params);
        list.forEach(t -> {
            Optional<SysCompany> first = Globals.companyList.stream().filter(c -> c.getId().equals(t.getCompanyId())).findFirst();
            if (first.isPresent()) {
                t.setCompanyName(first.get().getFullName());
            }
        });
        return list;
    }

    @Override
    public List<SourcePz> findJjflkms(Map<String, Object> params) {
        params.put("jjflcodes", Arrays.asList("30211", "30215", "30216"));
        List<SourcePz> list = sourcePzDao.groupByExt3(params);
        list.forEach(t -> {
            t.setJjkmCode(t.getExt3());
            String jjflName = "";
            switch (t.getExt3()) {
                case "30211":
                    jjflName = "差旅费";
                    break;
                case "30215":
                    jjflName = "会议费";
                    break;
                case "30216":
                    jjflName = "培训费";
                    break;
            }
            t.setJjkmName(jjflName);
        });
        list.sort(Comparator.comparing(SourcePz::getCompanyId)
                .thenComparing(SourcePz::getKjnd)
                .thenComparing(SourcePz::getKjqj)
                .thenComparing(SourcePz::getJjkmCode));
        return list;
    }


    //检查5.1. 收入科目检查：
    //     a) 会计科目：  1011 = 800101	 总发生额。
    //     b) 会计科目    6001 = 4001
    //	   c) 会计科目    4601 = 6601
    //	   d) 会计科目    4604 = 6604
    //	   e) 会计科目    4901 = 6901
    public List<SourcePzErrorDto> checkKmEqual(List<SourcePz> pzList) {
        List<SourcePzErrorDto> errorList = new ArrayList<>();
        HashMap<String, List<SourcePz>> companyList = pzList.stream().filter(
                t -> t.getKjkmCode().startsWith("1011")
                        || t.getKjkmCode().startsWith("800101")
                        || t.getKjkmCode().startsWith("4001")
                        || t.getKjkmCode().startsWith("6001")
                        || t.getKjkmCode().startsWith("4601")
                        || t.getKjkmCode().startsWith("6601")
                        || t.getKjkmCode().startsWith("4609")
                        || t.getKjkmCode().startsWith("6609")
        ).collect(Collectors.groupingBy(t -> t.getCompanyId(), HashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<SourcePz>> company : companyList.entrySet()) {
            HashMap<Integer, List<SourcePz>> kjndList = company.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjnd(), HashMap::new, Collectors.toList()));
            for (Map.Entry<Integer, List<SourcePz>> kjnd : kjndList.entrySet()) {
                HashMap<String, List<SourcePz>> kjkmList = kjnd.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjkmCode(), HashMap::new, Collectors.toList()));

                BigDecimal km1011 = BigDecimal.ZERO, km800101 = BigDecimal.ZERO;
                BigDecimal km4001 = BigDecimal.ZERO, km6001 = BigDecimal.ZERO;
                BigDecimal km4601 = BigDecimal.ZERO, km6601 = BigDecimal.ZERO;
                BigDecimal km4609 = BigDecimal.ZERO, km6609 = BigDecimal.ZERO;
                for (Map.Entry<String, List<SourcePz>> kjkm : kjkmList.entrySet()) {
                    switch (kjkm.getKey().substring(0, 4)) {
                        case "1011":
                            km1011 = km1011.add(kjkm.getValue().stream().map(SourcePz::getYe).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                            break;
                        case "8001":
                            km800101 = km800101.add(kjkm.getValue().stream().map(SourcePz::getYe).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                            break;
                        case "4001":
                            km4001 = km4001.add(kjkm.getValue().stream().map(SourcePz::getYe).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                            break;
                        case "6001":
                            km6001 = km6001.add(kjkm.getValue().stream().map(SourcePz::getYe).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                            break;
                        case "4601":
                            km4601 = km4601.add(kjkm.getValue().stream().map(SourcePz::getYe).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                            break;
                        case "6601":
                            km6601 = km6601.add(kjkm.getValue().stream().map(SourcePz::getYe).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                            break;
                        case "4609":
                            km4609 = km4609.add(kjkm.getValue().stream().map(SourcePz::getYe).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                            break;
                        case "6609":
                            km6609 = km6609.add(kjkm.getValue().stream().map(SourcePz::getYe).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                            break;
                    }
                }
                if (km1011.abs().compareTo(km800101.abs()) != 0) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
                    errorDto.setErrorCode(1);
                    errorDto.setErrorMsg("科目1011与800101余额存在差异");
                    errorList.add(errorDto);
                }
                if (km4001.compareTo(km6001) != 0) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
                    errorDto.setErrorCode(1);
                    errorDto.setErrorMsg("科目4001与6001余额存在差异");
                    errorList.add(errorDto);
                }
                if (km4601.compareTo(km6601) != 0) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
                    errorDto.setErrorCode(1);
                    errorDto.setErrorMsg("科目4601与6601余额存在差异");
                    errorList.add(errorDto);
                }
                if (km4609.compareTo(km6609) != 0) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
                    errorDto.setErrorCode(1);
                    errorDto.setErrorMsg("科目4609与6609余额存在差异");
                    errorList.add(errorDto);
                }
            }
        }

        return errorList;
    }


    //    5.2. 检查负数情况：
    //    a) 1,5,7开头的会计科目借方余额不能为负数，贷方余额不能有数   (排除1602，1702*)
    //    b) 2,3,4,6,8 开头的会计科目贷方余额不能为负数，借方余额不能有数 (排除3001*，3301*)
    public List<SourcePzErrorDto> checkKmNegative(List<SourcePz> pzList) {
        List<SourcePzErrorDto> errorList = new ArrayList<>();
        HashMap<String, List<SourcePz>> companyList = pzList.stream().filter(
                t -> !t.getKjkmCode().startsWith("1602")
                        && !t.getKjkmCode().startsWith("1702")
                        && !t.getKjkmCode().startsWith("3001")
                        && !t.getKjkmCode().startsWith("3301")
        ).collect(Collectors.groupingBy(t -> t.getCompanyId(), HashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<SourcePz>> company : companyList.entrySet()) {
            HashMap<Integer, List<SourcePz>> kjndList = company.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjnd(), HashMap::new, Collectors.toList()));
            for (Map.Entry<Integer, List<SourcePz>> kjnd : kjndList.entrySet()) {
                HashMap<String, List<SourcePz>> kjkmList = kjnd.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjkmCode(), HashMap::new, Collectors.toList()));

                for (Map.Entry<String, List<SourcePz>> kjkm : kjkmList.entrySet()) {
                    BigDecimal total = BigDecimal.ZERO;
                    if (kjkm.getKey().startsWith("1")) {
                        kjkm.getValue().forEach(c -> c.setYe(c.getJ().subtract(c.getD())));
                        total = total.add(kjkm.getValue().stream().map(SourcePz::getYe).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                    } else if (kjkm.getKey().startsWith("2")) {
                        kjkm.getValue().forEach(c -> c.setYe(c.getD().subtract(c.getJ())));
                        total = total.add(kjkm.getValue().stream().map(SourcePz::getYe).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                    }
                    if (total.compareTo(BigDecimal.ZERO) < 0) {
                        SourcePzErrorDto errorDto = new SourcePzErrorDto();
                        errorDto.setCompanyId(company.getKey());
                        errorDto.setKjnd(kjnd.getKey());
                        errorDto.setKjkmName(kjkm.getKey());
                        errorDto.setErrorCode(2);
                        errorDto.setErrorMsg("科目" + kjkm.getKey() + "余额为负数");
                        errorList.add(errorDto);
                    }
                }

            }
        }

        return errorList;
    }

    //检查年初余额负数
    @Override
    public List<SourcePzErrorDto> checkKmNcyeNegative(List<SourcePz> pzList) {
        List<SourcePzErrorDto> errorList = new ArrayList<>();
        HashMap<String, List<SourcePz>> companyList = pzList.stream().filter(t -> t.getVouKind().equals("QC")).collect(Collectors.groupingBy(t -> t.getCompanyId(), HashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<SourcePz>> company : companyList.entrySet()) {
            HashMap<Integer, List<SourcePz>> kjndList = company.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjnd(), HashMap::new, Collectors.toList()));
            for (Map.Entry<Integer, List<SourcePz>> kjnd : kjndList.entrySet()) {
                HashMap<String, List<SourcePz>> kjkmList = kjnd.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjkmCode(), HashMap::new, Collectors.toList()));

                for (Map.Entry<String, List<SourcePz>> kjkm : kjkmList.entrySet()) {
                    BigDecimal total = BigDecimal.ZERO;
                    total = total.add(kjkm.getValue().stream().map(SourcePz::getStadAmt).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                    if (total.compareTo(BigDecimal.ZERO) < 0) {
                        SourcePzErrorDto errorDto = new SourcePzErrorDto();
                        errorDto.setCompanyId(company.getKey());
                        errorDto.setKjnd(kjnd.getKey());
                        errorDto.setKjkmName(kjkm.getKey());
                        errorDto.setErrorCode(3);
                        errorDto.setErrorMsg("科目" + kjkm.getKey() + "期初余额为负数");
                        errorList.add(errorDto);
                    }
                }

            }
        }

        return errorList;
    }


    //5.3  零余额检查
    //    a) 1011和800101会计科目的余额必须为0 ，800101科目的辅助项累计余额也必须为0
    public List<SourcePzErrorDto> checkKmZero(List<SourcePz> pzList) {
        List<SourcePzErrorDto> errorList = new ArrayList<>();
        HashMap<String, List<SourcePz>> companyList = pzList.stream().filter(
                t -> t.getKjkmCode().startsWith("1011") || t.getKjkmCode().startsWith("800101")
        ).collect(Collectors.groupingBy(t -> t.getCompanyId(), HashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<SourcePz>> company : companyList.entrySet()) {
            HashMap<Integer, List<SourcePz>> kjndList = company.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjnd(), HashMap::new, Collectors.toList()));
            for (Map.Entry<Integer, List<SourcePz>> kjnd : kjndList.entrySet()) {
                HashMap<String, List<SourcePz>> kjkmList = kjnd.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjkmCode(), HashMap::new, Collectors.toList()));

                for (Map.Entry<String, List<SourcePz>> kjkm : kjkmList.entrySet()) {
                    BigDecimal total = BigDecimal.ZERO;
                    total = total.add(kjkm.getValue().stream().map(SourcePz::getYe).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                    if (total.compareTo(BigDecimal.ZERO) != 0) {
                        SourcePzErrorDto errorDto = new SourcePzErrorDto();
                        errorDto.setCompanyId(company.getKey());
                        errorDto.setKjnd(kjnd.getKey());
                        errorDto.setKjkmName(kjkm.getKey());
                        errorDto.setErrorCode(3);
                        errorDto.setErrorMsg("科目" + kjkm.getKey() + "余额不为0");
                        errorList.add(errorDto);
                    }
                }

            }
        }

        return errorList;
    }

    //5.4  经济分类支出检查
    //    a) 7开头的7* 辅助项记录余额（默认只有借方额）不能为负数。
    public List<SourcePzErrorDto> checkJjkmNegative(List<SourcePz> pzList) {
        List<SourcePzErrorDto> errorList = new ArrayList<>();
        HashMap<String, List<SourcePz>> companyList = pzList.stream().filter(
                t -> t.getKjkmCode().startsWith("7")
        ).collect(Collectors.groupingBy(t -> t.getCompanyId(), HashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<SourcePz>> company : companyList.entrySet()) {
            HashMap<Integer, List<SourcePz>> kjndList = company.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjnd(), HashMap::new, Collectors.toList()));
            for (Map.Entry<Integer, List<SourcePz>> kjnd : kjndList.entrySet()) {
                HashMap<String, List<SourcePz>> kjkmList = kjnd.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjkmCode(), HashMap::new, Collectors.toList()));

                for (Map.Entry<String, List<SourcePz>> kjkm : kjkmList.entrySet()) {
                    BigDecimal total = BigDecimal.ZERO;
                    kjkm.getValue().forEach(c -> c.setYe(c.getJ().subtract(c.getD())));
                    total = total.add(kjkm.getValue().stream().map(SourcePz::getYe).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                    if (total.compareTo(BigDecimal.ZERO) < 0) {
                        SourcePzErrorDto errorDto = new SourcePzErrorDto();
                        errorDto.setCompanyId(company.getKey());
                        errorDto.setKjnd(kjnd.getKey());
                        errorDto.setKjkmName(kjkm.getKey());
                        errorDto.setErrorCode(4);
                        errorDto.setErrorMsg("科目" + kjkm.getKey() + "存在负数记录");
                        errorList.add(errorDto);
                    }
                }

            }
        }

        return errorList;
    }


    //  5.5  项目检查
    //    a) 预算项目维度：科目核算  8开头的8*（剔除8001开头的8001*）的期初数 + 6开头的6* 的余额 - 7开头的7*余额 结果不能为负数
    public List<SourcePzErrorDto> checkXmNegative(List<SourcePz> pzList) {
        List<SourcePzErrorDto> errorList = new ArrayList<>();
        HashMap<String, List<SourcePz>> companyList = pzList.stream().filter(
                t -> (t.getKjkmCode().startsWith("8") && !t.getKjkmCode().startsWith("8001"))
                        || t.getKjkmCode().startsWith("6")
                        || t.getKjkmCode().startsWith("7")
        ).collect(Collectors.groupingBy(t -> t.getCompanyId(), HashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<SourcePz>> company : companyList.entrySet()) {

            //填充预算列
            //fillExtData(company.getKey(), company.getValue(), "DEPPRO");

            HashMap<Integer, List<SourcePz>> kjndList = company.getValue().stream().filter(t -> StringUtil.isNotEmpty(t.getYsxmCode())).collect(Collectors.groupingBy(t -> t.getKjnd(), HashMap::new, Collectors.toList()));
            for (Map.Entry<Integer, List<SourcePz>> kjnd : kjndList.entrySet()) {
                HashMap<String, List<SourcePz>> ysxmList = kjnd.getValue().stream().collect(Collectors.groupingBy(t -> t.getYsxmCode(), HashMap::new, Collectors.toList()));

                for (Map.Entry<String, List<SourcePz>> ysxm : ysxmList.entrySet()) {
                    String ysxmName = ysxm.getKey();
                    Optional<GdszczMaEleDeppro> ysxmOption = Globals.depproList.stream().filter(c -> c.getAgencyCode().equals(company.getKey()) && c.getSetYear().equals(kjnd.getKey()) && c.getChrCode().equals(ysxm.getKey())).findFirst();
                    if (ysxmOption.isPresent()) {
                        ysxmName = ysxm.getKey() + " " + ysxmOption.get().getChrName();
                    }

                    BigDecimal total = BigDecimal.ZERO;
                    for (SourcePz pz : ysxm.getValue()) {
                        if (pz.getKjkmCode().startsWith("8")) {
                            total = total.add(pz.getJ());
                        } else if (pz.getKjkmCode().startsWith("6")) {
                            total = total.add(pz.getD());
                        } else if (pz.getKjkmCode().startsWith("7")) {
                            total = total.subtract(pz.getJ());
                        }
                    }
                    if (total.compareTo(BigDecimal.ZERO) < 0) {
                        SourcePzErrorDto errorDto = new SourcePzErrorDto();
                        errorDto.setCompanyId(company.getKey());
                        errorDto.setCompanyName(kjnd.getValue().get(0).getCompanyName());
                        errorDto.setKjnd(kjnd.getKey());
                        errorDto.setKjkmName(ysxm.getKey());
                        errorDto.setErrorCode(5);
                        errorDto.setErrorMsg("预算项目" + ysxmName + "  8开头的8*（剔除8001开头的8001*）的期初数 + 6开头的6* 的余额 - 7开头的7*余额为负数 ");
                        errorList.add(errorDto);
                    }
                }

            }
        }

        return errorList;
    }

    //5.6  经济分类支出占比超过30%提醒
    //      710101，720101 会计科目
    //	  720101，720102 会计科目
    //	  30199/301，  30299/302，30399/303，30999/309，31099/310  占比必须小于30%；
    public List<SourcePzErrorDto> checkJjkmPercent(List<SourcePz> pzList) {
        List<SourcePzErrorDto> errorList = new ArrayList<>();
        HashMap<String, List<SourcePz>> companyList = pzList.stream().filter(
                t -> t.getKjkmCode().startsWith("710101")
                        || t.getKjkmCode().startsWith("710102")
                        || t.getKjkmCode().startsWith("720101")
                        || t.getKjkmCode().startsWith("720102")
        ).collect(Collectors.groupingBy(t -> t.getCompanyId(), HashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<SourcePz>> company : companyList.entrySet()) {

            HashMap<String, List<SourcePz>> kjkmList = company.getValue().stream().filter(
                    t -> StringUtil.isNotEmpty(t.getJjkmCode())
                            && (t.getJjkmCode().startsWith("301")
                            || t.getJjkmCode().startsWith("302")
                            || t.getJjkmCode().startsWith("303")
                            || t.getJjkmCode().startsWith("309")
                            || t.getJjkmCode().startsWith("310"))
            ).collect(Collectors.groupingBy(t -> t.getKjnd() + "_" + t.getKjkmCode(), HashMap::new, Collectors.toList()));


            for (Map.Entry<String, List<SourcePz>> kjkm : kjkmList.entrySet()) {
                HashMap<String, List<SourcePz>> jjkmList = kjkm.getValue().stream().collect(Collectors.groupingBy(t -> t.getJjkmCode(), HashMap::new, Collectors.toList()));

                BigDecimal jj30199 = BigDecimal.ZERO, jj301 = BigDecimal.ZERO;
                BigDecimal jj30299 = BigDecimal.ZERO, jj302 = BigDecimal.ZERO;
                BigDecimal jj30399 = BigDecimal.ZERO, jj303 = BigDecimal.ZERO;
                BigDecimal jj30999 = BigDecimal.ZERO, jj309 = BigDecimal.ZERO;
                BigDecimal jj31099 = BigDecimal.ZERO, jj310 = BigDecimal.ZERO;
                for (Map.Entry<String, List<SourcePz>> ysxm : jjkmList.entrySet()) {
                    if (ysxm.getKey().startsWith("301")) {
                        jj301 = jj301.add(ysxm.getValue().stream().map(SourcePz::getJ).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                        if (ysxm.getKey().equals("30199")) {
                            jj30199 = jj30199.add(ysxm.getValue().stream().map(SourcePz::getJ).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                        }
                    } else if (ysxm.getKey().startsWith("302")) {
                        jj302 = jj302.add(ysxm.getValue().stream().map(SourcePz::getJ).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                        if (ysxm.getKey().equals("30299")) {
                            jj30299 = jj30299.add(ysxm.getValue().stream().map(SourcePz::getJ).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                        }
                    } else if (ysxm.getKey().startsWith("303")) {
                        jj303 = jj303.add(ysxm.getValue().stream().map(SourcePz::getJ).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                        if (ysxm.getKey().equals("30399")) {
                            jj30399 = jj30399.add(ysxm.getValue().stream().map(SourcePz::getJ).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                        }
                    } else if (ysxm.getKey().startsWith("309")) {
                        jj309 = jj309.add(ysxm.getValue().stream().map(SourcePz::getJ).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                        if (ysxm.getKey().equals("30999")) {
                            jj30999 = jj30999.add(ysxm.getValue().stream().map(SourcePz::getJ).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                        }
                    } else if (ysxm.getKey().startsWith("310")) {
                        jj310 = jj310.add(ysxm.getValue().stream().map(SourcePz::getJ).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                        if (ysxm.getKey().equals("31099")) {
                            jj31099 = jj31099.add(ysxm.getValue().stream().map(SourcePz::getJ).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                        }
                    }
                }
                if (jj301.compareTo(BigDecimal.ZERO) > 0 && jj30199.divide(jj301, BigDecimal.ROUND_HALF_UP).compareTo(BigDecimal.valueOf(0.3)) > 0) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(Integer.parseInt(kjkm.getKey().split("_")[0]));
                    errorDto.setErrorCode(6);
                    errorDto.setErrorMsg("科目" + kjkm.getKey().split("_")[1] + ":" + "经济分类支出30199超过30%");
                    errorList.add(errorDto);
                }
                if (jj302.compareTo(BigDecimal.ZERO) > 0 && jj30299.divide(jj302, BigDecimal.ROUND_HALF_UP).compareTo(BigDecimal.valueOf(0.3)) > 0) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(Integer.parseInt(kjkm.getKey().split("_")[0]));
                    errorDto.setErrorCode(6);
                    errorDto.setErrorMsg("科目" + kjkm.getKey().split("_")[1] + ":" + "经济分类支出30299超过30%");
                    errorList.add(errorDto);
                }
                if (jj303.compareTo(BigDecimal.ZERO) > 0 && jj30399.divide(jj303, BigDecimal.ROUND_HALF_UP).compareTo(BigDecimal.valueOf(0.3)) > 0) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(Integer.parseInt(kjkm.getKey().split("_")[0]));
                    errorDto.setErrorCode(6);
                    errorDto.setErrorMsg("科目" + kjkm.getKey().split("_")[1] + ":" + "经济分类支出30399超过30%");
                    errorList.add(errorDto);
                }
                if (jj309.compareTo(BigDecimal.ZERO) > 0 && jj30999.divide(jj309, BigDecimal.ROUND_HALF_UP).compareTo(BigDecimal.valueOf(0.3)) > 0) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(Integer.parseInt(kjkm.getKey().split("_")[0]));
                    errorDto.setErrorCode(6);
                    errorDto.setErrorMsg("科目" + kjkm.getKey().split("_")[1] + ":" + "经济分类支出30999超过30%");
                    errorList.add(errorDto);
                }
                if (jj310.compareTo(BigDecimal.ZERO) > 0 && jj31099.divide(jj310, BigDecimal.ROUND_HALF_UP).compareTo(BigDecimal.valueOf(0.3)) > 0) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(Integer.parseInt(kjkm.getKey().split("_")[0]));
                    errorDto.setErrorCode(6);
                    errorDto.setErrorMsg("科目" + kjkm.getKey().split("_")[1] + ":" + "经济分类支出31099超过30%");
                    errorList.add(errorDto);
                }
            }
        }

        return errorList;
    }

    /**
     * 1，	检查5001的费用类型对应7001/7101的部门支出经济分类：101-301,201-302,301-303。检查出差异凭证号
     */
    @Override
    public List<SourcePz> checkCostBgtEcoEqual(List<SourcePz> pzList) {
        List<SourcePz> errorList = new ArrayList<>();
        HashMap<String, List<SourcePz>> companyList = pzList.stream().filter(
                t -> t.getKjkmCode().startsWith("7101")
                        || t.getKjkmCode().startsWith("5001")
        ).collect(Collectors.groupingBy(t -> t.getCompanyId(), HashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<SourcePz>> company : companyList.entrySet()) {
            List<SourcePz> kjkm5001List = company.getValue().stream().filter(t -> t.getKjkmCode().startsWith("5001") && (t.getCosttypeCode().equals("01") || t.getCosttypeCode().equals("02") || t.getCosttypeCode().equals("03"))).collect(Collectors.toList());
            List<SourcePz> kjkm7101List = company.getValue().stream().filter(t -> t.getKjkmCode().startsWith("7101") && (t.getJjkmCode().startsWith("301") || t.getJjkmCode().startsWith("302") || t.getJjkmCode().startsWith("303"))).collect(Collectors.toList());

            for (int i = 0; i < kjkm5001List.size(); i++) {
                for (int j = 0; j < kjkm7101List.size(); j++) {
                    if (kjkm5001List.get(i).getJ().equals(kjkm7101List.get(j).getJ())
                            && kjkm5001List.get(i).getPzrq().equals(kjkm7101List.get(j).getPzrq())
                            && kjkm5001List.get(i).getPzh().equals(kjkm7101List.get(j).getPzh())
                    ) {
                        kjkm7101List.remove(j);
                        j--;

                        kjkm5001List.remove(i);
                        i--;
                        break;
                    }
                }
            }
            HashMap<String, List<SourcePz>> map = kjkm7101List.stream().collect(Collectors.groupingBy(t -> t.getPzrq() + "_" + t.getPzh() + "_" + t.getZy(), HashMap::new, Collectors.toList()));
            List<SourcePz> kjkm7101List2 = new ArrayList<>();
            for (Map.Entry<String, List<SourcePz>> item : map.entrySet()) {
                BigDecimal amount = BigDecimal.ZERO;
                amount = amount.add(item.getValue().stream().map(SourcePz::getJ).reduce(BigDecimal.ZERO, (a, b) -> a.add(b)));
                item.getValue().get(0).setJ(amount);
                kjkm7101List2.add(item.getValue().get(0));
            }
            for (int i = 0; i < kjkm5001List.size(); i++) {
                for (int j = 0; j < kjkm7101List2.size(); j++) {
                    if (kjkm5001List.get(i).getJ().equals(kjkm7101List2.get(j).getJ())
                            && kjkm5001List.get(i).getPzrq().equals(kjkm7101List2.get(j).getPzrq())
                            && kjkm5001List.get(i).getPzh().equals(kjkm7101List2.get(j).getPzh())
                    ) {
                        kjkm5001List.remove(i);
                        i--;
                        kjkm7101List2.remove(j);
                        j--;
                    }
                }
            }
            errorList.addAll(kjkm5001List);
            errorList.addAll(kjkm7101List2);
        }

        return errorList;
    }

    @Override
    public List<SourcePzErrorDto> checkKjkmExists(List<SourcePz> pzList) {
        List<SourcePzErrorDto> errorList = new ArrayList<>();
        HashMap<String, List<SourcePz>> companyList = pzList.stream().collect(Collectors.groupingBy(t -> t.getCompanyId(), HashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<SourcePz>> company : companyList.entrySet()) {
            HashMap<Integer, List<SourcePz>> kjndList = company.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjnd(), HashMap::new, Collectors.toList()));
            for (Map.Entry<Integer, List<SourcePz>> kjnd : kjndList.entrySet()) {
                List<SourcePz> list = kjnd.getValue().stream().filter(t -> t.getKjkmCode().startsWith("4601")).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(list)) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
                    errorDto.setErrorCode(1);
                    errorDto.setErrorMsg("科目4601没有发生额");
                    errorList.add(errorDto);
                }

            }
        }

        return errorList;
    }

    @Override
    public List<SourcePz> checkKjkmSrExists(List<SourcePz> pzList) {
        List<SourcePz> errorList = new ArrayList<>();
        HashMap<String, List<SourcePz>> companyList = pzList.stream().collect(Collectors.groupingBy(t -> t.getCompanyId(), HashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<SourcePz>> company : companyList.entrySet()) {
            HashMap<Integer, List<SourcePz>> kjndList = company.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjnd(), HashMap::new, Collectors.toList()));
            for (Map.Entry<Integer, List<SourcePz>> kjnd : kjndList.entrySet()) {
                List<SourcePz> list = kjnd.getValue().stream().filter(t -> t.getKjkmCode().startsWith("100201") && t.getJ().compareTo(BigDecimal.ZERO) > 0 && t.getZy().contains("饭堂")).collect(Collectors.toList());
                errorList.addAll(list);
            }
        }

        return errorList;
    }

    @Override
    public List<SourcePzErrorDto> checkKmNegative48(List<SourcePz> pzList) {
        List<SourcePzErrorDto> errorList = new ArrayList<>();
        HashMap<String, List<SourcePz>> companyList = pzList.stream().filter(
                t -> t.getKjkmCode().startsWith("4601")
                        || t.getKjkmCode().startsWith("4609")
                        || t.getKjkmCode().startsWith("6001")
                        || t.getKjkmCode().startsWith("6601")
                        || t.getKjkmCode().startsWith("6901")
                        || t.getKjkmCode().startsWith("71010102")
                        || t.getKjkmCode().startsWith("71010103")
                        || t.getKjkmCode().startsWith("71010202")
                        || t.getKjkmCode().startsWith("71010203")
                        || t.getKjkmCode().startsWith("8201")
        ).collect(Collectors.groupingBy(t -> t.getCompanyId(), HashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<SourcePz>> company : companyList.entrySet()) {
            HashMap<Integer, List<SourcePz>> kjndList = company.getValue().stream().collect(Collectors.groupingBy(t -> t.getKjnd(), HashMap::new, Collectors.toList()));
            for (Map.Entry<Integer, List<SourcePz>> kjnd : kjndList.entrySet()) {
                boolean km4601 = false, km4609 = false, km6001 = false, km6601 = false, km6901 = false;
                boolean km71010102 = false, km71010103 = false, km71010202 = false, km71010203 = false, km8201 = false;

                if (kjnd.getValue().stream().filter(t -> t.getKjkmCode().startsWith("4601")).count() > 0) {
                    km4601 = true;
                }
                if (kjnd.getValue().stream().filter(t -> t.getKjkmCode().startsWith("4609")).count() > 0) {
                    km4609 = true;
                }
                if (kjnd.getValue().stream().filter(t -> t.getKjkmCode().startsWith("6001")).count() > 0) {
                    km6001 = true;
                }
                if (kjnd.getValue().stream().filter(t -> t.getKjkmCode().startsWith("6601")).count() > 0) {
                    km6601 = true;
                }
                if (kjnd.getValue().stream().filter(t -> t.getKjkmCode().startsWith("6901")).count() > 0) {
                    km6901 = true;
                }
                if (kjnd.getValue().stream().filter(t -> t.getKjkmCode().startsWith("71010102")).count() > 0) {
                    km71010102 = true;
                }
                if (kjnd.getValue().stream().filter(t -> t.getKjkmCode().startsWith("71010103")).count() > 0) {
                    km71010103 = true;
                }
                if (kjnd.getValue().stream().filter(t -> t.getKjkmCode().startsWith("71010202")).count() > 0) {
                    km71010202 = true;
                }
                if (kjnd.getValue().stream().filter(t -> t.getKjkmCode().startsWith("71010203")).count() > 0) {
                    km71010203 = true;
                }
                if (kjnd.getValue().stream().filter(t -> t.getKjkmCode().startsWith("8201")).count() > 0) {
                    km8201 = true;
                }

                if (!km4601) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
//                    errorDto.setKjkmName(kjkm.getKey());
                    errorDto.setErrorCode(2);
                    errorDto.setErrorMsg("科目4601没有发生额");
                    errorList.add(errorDto);
                }
                if (!km4609) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
//                    errorDto.setKjkmName(kjkm.getKey());
                    errorDto.setErrorCode(2);
                    errorDto.setErrorMsg("科目4609没有发生额");
                    errorList.add(errorDto);
                }
                if (!km6001) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
//                    errorDto.setKjkmName(kjkm.getKey());
                    errorDto.setErrorCode(2);
                    errorDto.setErrorMsg("科目6001没有发生额");
                    errorList.add(errorDto);
                }
                if (!km6601) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
//                    errorDto.setKjkmName(kjkm.getKey());
                    errorDto.setErrorCode(2);
                    errorDto.setErrorMsg("科目6601没有发生额");
                    errorList.add(errorDto);
                }
                if (!km6901) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
//                    errorDto.setKjkmName(kjkm.getKey());
                    errorDto.setErrorCode(2);
                    errorDto.setErrorMsg("科目6901没有发生额");
                    errorList.add(errorDto);
                }
                if (!km71010102) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
//                    errorDto.setKjkmName(kjkm.getKey());
                    errorDto.setErrorCode(2);
                    errorDto.setErrorMsg("科目71010102没有发生额");
                    errorList.add(errorDto);
                }
                if (!km71010103) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
//                    errorDto.setKjkmName(kjkm.getKey());
                    errorDto.setErrorCode(2);
                    errorDto.setErrorMsg("科目71010103没有发生额");
                    errorList.add(errorDto);
                }
                if (!km71010202) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
//                    errorDto.setKjkmName(kjkm.getKey());
                    errorDto.setErrorCode(2);
                    errorDto.setErrorMsg("科目71010202没有发生额");
                    errorList.add(errorDto);
                }
                if (!km71010203) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
//                    errorDto.setKjkmName(kjkm.getKey());
                    errorDto.setErrorCode(2);
                    errorDto.setErrorMsg("科目71010203没有发生额");
                    errorList.add(errorDto);
                }
                if (!km8201) {
                    SourcePzErrorDto errorDto = new SourcePzErrorDto();
                    errorDto.setCompanyId(company.getKey());
                    errorDto.setKjnd(kjnd.getKey());
//                    errorDto.setKjkmName(kjkm.getKey());
                    errorDto.setErrorCode(2);
                    errorDto.setErrorMsg("科目8201没有发生额");
                    errorList.add(errorDto);
                }
            }
        }

        return errorList;
    }


    /**
     * 填充预算项目
     */
    private void fillExtData(String companyId, List<SourcePz> pzList, String CUSTOMITEMCODE) {
        Map<String, Object> param = new HashMap<>();
        param.put("companyId", companyId);
        param.put("itemCode", CUSTOMITEMCODE);
        List<SourceBaseCustomValue> customValueAllList = sourceBaseCustomValueDao.findAll(param);
        List<SourceBaseKjkmExt> kjkmExtAllList = sourceBaseKjkmExtDao.findAll(param);

        Map<String, List<SourcePz>> collect = pzList.stream().collect(Collectors.groupingBy(t -> t.getKjnd() + "_" + t.getKjkmCode(), HashMap::new, Collectors.toList()));
        List<SourceBaseKjkmExt> kjkmExts;
        for (Map.Entry<String, List<SourcePz>> entry : collect.entrySet()) {
            String key = entry.getKey();
            Integer kjnd = Integer.parseInt(key.split("_")[0]);
            String kjkmCode = key.split("_")[1];

            kjkmExts = kjkmExtAllList.stream().filter(t -> t.getCompanyId().equals(companyId) && t.getKjnd().equals(kjnd) && t.getKjkmCode().equals(kjkmCode)).collect(Collectors.toList());
            kjkmExts.forEach(t -> {
                for (SourcePz auditModelStep2 : entry.getValue()) {
                    Optional<SourceBaseCustomValue> first = null;
                    switch (t.getExtCode()) {
                        case "1":
                            first = customValueAllList.stream().filter(c -> c.getCompanyId().equals(companyId) && c.getKjnd().equals(kjnd) && c.getItemCode().equals(CUSTOMITEMCODE) && c.getCode().equals(auditModelStep2.getExt1())).findFirst();
                            break;
                        case "2":
                            first = customValueAllList.stream().filter(c -> c.getCompanyId().equals(companyId) && c.getKjnd().equals(kjnd) && c.getItemCode().equals(CUSTOMITEMCODE) && c.getCode().equals(auditModelStep2.getExt2())).findFirst();
                            break;
                        case "3":
                            first = customValueAllList.stream().filter(c -> c.getCompanyId().equals(companyId) && c.getKjnd().equals(kjnd) && c.getItemCode().equals(CUSTOMITEMCODE) && c.getCode().equals(auditModelStep2.getExt3())).findFirst();
                            break;
                        case "4":
                            first = customValueAllList.stream().filter(c -> c.getCompanyId().equals(companyId) && c.getKjnd().equals(kjnd) && c.getItemCode().equals(CUSTOMITEMCODE) && c.getCode().equals(auditModelStep2.getExt4())).findFirst();
                            break;
                        case "5":
                            first = customValueAllList.stream().filter(c -> c.getCompanyId().equals(companyId) && c.getKjnd().equals(kjnd) && c.getItemCode().equals(CUSTOMITEMCODE) && c.getCode().equals(auditModelStep2.getExt5())).findFirst();
                            break;
                        case "6":
                            first = customValueAllList.stream().filter(c -> c.getCompanyId().equals(companyId) && c.getKjnd().equals(kjnd) && c.getItemCode().equals(CUSTOMITEMCODE) && c.getCode().equals(auditModelStep2.getExt6())).findFirst();
                            break;
                        case "7":
                            first = customValueAllList.stream().filter(c -> c.getCompanyId().equals(companyId) && c.getKjnd().equals(kjnd) && c.getItemCode().equals(CUSTOMITEMCODE) && c.getCode().equals(auditModelStep2.getExt7())).findFirst();
                            break;
                        case "8":
                            first = customValueAllList.stream().filter(c -> c.getCompanyId().equals(companyId) && c.getKjnd().equals(kjnd) && c.getItemCode().equals(CUSTOMITEMCODE) && c.getCode().equals(auditModelStep2.getExt8())).findFirst();
                            break;
                        case "9":
                            first = customValueAllList.stream().filter(c -> c.getCompanyId().equals(companyId) && c.getKjnd().equals(kjnd) && c.getItemCode().equals(CUSTOMITEMCODE) && c.getCode().equals(auditModelStep2.getExt9())).findFirst();
                            break;
                        case "10":
                            first = customValueAllList.stream().filter(c -> c.getCompanyId().equals(companyId) && c.getKjnd().equals(kjnd) && c.getItemCode().equals(CUSTOMITEMCODE) && c.getCode().equals(auditModelStep2.getExt10())).findFirst();
                            break;
                        case "11":
                            first = customValueAllList.stream().filter(c -> c.getCompanyId().equals(companyId) && c.getKjnd().equals(kjnd) && c.getItemCode().equals(CUSTOMITEMCODE) && c.getCode().equals(auditModelStep2.getExt11())).findFirst();
                            break;
                        case "12":
                            first = customValueAllList.stream().filter(c -> c.getCompanyId().equals(companyId) && c.getKjnd().equals(kjnd) && c.getItemCode().equals(CUSTOMITEMCODE) && c.getCode().equals(auditModelStep2.getExt12())).findFirst();
                            break;
                    }
                    if (first != null && first.isPresent()) {
                        if (CUSTOMITEMCODE.equals("DEPPRO")) { //预算项目
                            auditModelStep2.setYsxmCode(first.get().getCode());
                            auditModelStep2.setYsxmName(first.get().getName());
                        } else if (CUSTOMITEMCODE.equals("EXPECO")) { //支出经济分类
                            auditModelStep2.setJjkmCode(first.get().getCode());
                            auditModelStep2.setJjkmName(first.get().getName());
                        }
                    }
                }
            });

        }

    }
}
